package cate.game.role.farm.island.po;

import cate.common.table.d.GDIsland;
import cate.common.table.farm.island.row.IslandGainRow;
import cate.common.util.GameResult;
import cate.game.play.fighter.HeroFighter;
import cate.game.play.param.HpExtend;
import cate.game.res.MixRes;
import cate.game.role.Role;
import cate.game.role.RoleDependent;
import cate.game.role.bag.hero.Hero;
import cate.game.role.farm.island.cell.AidHeroCell;
import cate.game.role.farm.island.cell.GainCell;
import cate.game.role.farm.island.msg.IslandAidHeroUpdateResp;
import cate.game.role.farm.island.msg.IslandGainAddResp;
import cate.game.role.farm.island.msg.IslandHeroStateResp;
import cate.game.role.farm.island.msg.IslandRewardUpdateResp;
import cate.game.role.fight.FuncPosition;
import cate.game.role.fight.HeroGrid;
import cate.game.role.fight.Position;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.function.Predicate;

@NoteClass(value = "迷失神庙冒险状态记录")
public class IslandStateRecord extends RoleDependent {
    @NoteField(value = "英雄血量状态", detail = "只记录受伤的英雄")
    public List<HeroState> heroStates;

    @NoteField(value = "选择的增益")
    public List<Gain> gains;

    @NoteField(value = "支援的英雄")
    public List<Hero> aidHeros;

    @NoteField(value = "累积获得的奖励")
    public MixRes reward;

    @NoteField(value = "女娲石技能是否生效")
    public boolean stoneSkillActive;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (heroStates == null) {
            heroStates = new ArrayList<>();
        }
        if (gains == null) {
            gains = new ArrayList<>();
        }
        gains.removeIf(a -> a.getRow(role.getGame()) == null);
        if (aidHeros == null) {
            aidHeros = new ArrayList<>();
        }
        for (Hero aidHero : aidHeros) {
            aidHero.initialize(role);
        }
        if (reward == null) {
            reward = new MixRes();
        }
    }

    /** 群体治疗 */
    public GameResult<Void> heal() {
        GameResult<Void> r = new GameResult<>();
        heroStates.forEach(a -> a.heal(GDIsland.SPRING_HEAL_RATE));
        heroStates.removeIf(HeroState::isFull);
        noticeHeroStateUpdate();
        role.getGame().notice.message(role, "灵泉使用成功");
        return r.success();
    }

    /** 复活单个英雄 */
    public GameResult<Void> reviveSingle() {
        GameResult<Void> r = new GameResult<>();
        if (heroStates.isEmpty()) {
            role.getGame().notice.message(role, "使用成功");
            return r.success();
        }
        heroStates.sort(Comparator.comparing(a -> a.hpRate));
        HeroState state = heroStates.get(0);
        if (state.isDead()) {
            state.hpRate = GDIsland.RESPAWN_HEAL_RATE;
        } else {
            heroStates.remove(0);
        }
        noticeHeroStateUpdate();
        role.getGame().notice.message(role, "使用成功");
        return r.success();
    }

    /** 选助阵英雄 */
    public GameResult<Void> pickHero(AidHeroCell heroCell, int index) {
        GameResult<Void> r = new GameResult<>();
        Hero hero = heroCell.getHeroByIndex(index);
        if (hero == null) {
            return r.fail("所选英雄不存在");
        }
        Hero aidHero = hero.copy();
        aidHero.initialize(role);
        this.aidHeros.add(aidHero);
        role.sendNow(new IslandAidHeroUpdateResp(hero));
        return r.success("雇佣成功");
    }

    /** 选增益处理 */
    public GameResult<Void> pickGain(GainCell skillCell, int index) {
        GameResult<Void> r = new GameResult<>();
        Integer gainId = skillCell.getGainByIndex(index);
        if (gainId == null) {
            return r.fail("所选增益不存在");
        }
        IslandGainRow row = role.getGame().table.island.gain.get(gainId);
        if(row == null){
            return r.fail("所选增益不存在");
        }
        Gain gain = new Gain(gainId);
        this.gains.add(gain);
        role.sendNow(new IslandGainAddResp(gain));
        role.getGame().notice.message(role, "增益选择成功");
        return r.success();
    }

    /** 更新英雄状态 */
    public void updateHeroState(List<HeroFighter> heroFighters) {
        heroFighters.forEach(
                f -> {
                    getHeroState(f.uid, true).update(f);
                });
        heroStates.removeIf(HeroState::isFull);
    }

    @JsonIgnore
    private HeroState getHeroState(String heroUid, boolean createWhenNull) {
        for (HeroState state : heroStates) {
            if (StringUtils.equals(state.heroUid, heroUid)) {
                return state;
            }
        }
        if (createWhenNull) {
            HeroState state = new HeroState();
            heroStates.add(state);
            return state;
        }
        return null;
    }

    /**
     * 构建血量继承对象
     *
     * @return
     */
    public HpExtend buildHpExtend(int funcId, int positionNum) {
        HpExtend hpExtend = new HpExtend();
        Position position = role.getFight().getPosition(funcId, positionNum);
        if (position != null) {
            for (HeroGrid grid : position.grids) {
                Hero hero = role.getBag().hero.getItem(grid.uid);
                // 背包里没有说明是援助英雄
                if (hero == null) {
                    hero = searchAidHero(grid.uid);
                }
                // 如果还找不到说明这个英雄已经没了
                if (hero == null) {
                    continue;
                }
                for (HeroState heroState : heroStates) {
                    if (StringUtils.equals(hero.uid, heroState.heroUid)) {
                        hpExtend.recordByHeroUid(heroState.heroUid, heroState.hpRate);
                        break;
                    }
                }
            }
        }
        return hpExtend;
    }

    public void addReward(MixRes reward) {
        this.reward.addList(reward);
        noticeRewardUpdate();
    }

    public Hero searchAidHero(String uid) {
        for (Hero hero : aidHeros) {
            if (StringUtils.equals(hero.uid, uid)) {
                return hero;
            }
        }
        return null;
    }

    /**
     * 获取生效的增益(根据原型过滤)
     * @return
     */
    @JsonIgnore
    public List<Gain> getActiveGain(){
        List<Gain> result = new ArrayList<>();
        Map<Integer, Gain> protoGainMap = new HashMap<>();
        for (Gain gain : gains) {
            IslandGainRow row = gain.getRow(role.getGame());
            if (row.protoId > 0) {
                Gain oldGain = protoGainMap.get(row.protoId);
                if (oldGain != null && oldGain.gainId > gain.gainId) {

                } else {
                    protoGainMap.put(row.protoId, gain);
                }
            } else {
                result.add(gain);
            }
        }
        result.addAll(protoGainMap.values());
        return result;
    }

    public void clear() {
        heroStates.clear();
        gains.clear();
        aidHeros.clear();
        reward.clear();
        stoneSkillActive = false;
    }

    public void useStone(){
        heroStates.clear();
        stoneSkillActive = true;
        noticeHeroStateUpdate();
    }

    public void noticeHeroStateUpdate() {
        role.sendNow(new IslandHeroStateResp(heroStates));
    }

    public void noticeRewardUpdate() {
        role.sendNow(new IslandRewardUpdateResp(reward));
    }

    public Predicate<Hero> aliveHeroRule() {
        return e -> {
            HeroState heroState = getHeroState(e.uid, false);
            return heroState == null || heroState.hpRate > 0;
        };
    }

    public boolean checkHerosAlive(FuncPosition funcPosition) {
        for (Position position : funcPosition.positions) {
            for (HeroGrid hg : position.grids) {
                HeroState hs = getHeroState(hg.uid, false);
                if (hs != null && hs.hpRate <= 0) {
                    return false;
                }
            }
        }
        return true;
    }
}
